package com.ionehe.group.common.wechat.component;

import cn.hutool.core.util.StrUtil;
import com.ionehe.group.common.wechat.config.WechatConfig;
import com.ionehe.group.common.wechat.enums.WechatEnv;
import com.ionehe.group.common.wechat.exception.WechatException;
import com.ionehe.group.common.wechat.model.AccessToken;
import com.ionehe.group.common.wechat.model.Code2Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * 微信openid缓存
 *
 *@author 2022/1/7 <a href="mailto:a@ionehe.com">xiu</a>
 */
@Component
@Slf4j
public class WechatOpenidCache {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private WechatAPI wechatAPI;
    private static final Integer duration = 120;
    private static final String wxCode2openIdHead = "wechat:code:";

    public String findOpenId(String code, WechatConfig config, WechatEnv env) {
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        String openId = operations.get(getKey(wxCode2openIdHead, code));

        if (StrUtil.isEmpty(openId)) {
            log.info("WechatOpenIdCache[]findOpenId[] start to get openId from WX, code:{},env:{}", code, env);

            switch (env) {
                case WECHAT_MINI_PROGRAM:
                    Code2Session code2Session = wechatAPI.getOpenIdMiniPro(code, config);
                    if (code2Session != null) {
                        log.info("WechatOpenIdCache[]findOpenId[] code:{},code2Session:{}", code, code2Session);
                        openId = code2Session.getOpenid();
                    } else {
                        log.error("WechatOpenIdCache[]findOpenId[] get openId by code failed[] code:{}", code);
                        throw new WechatException("accessToken null error");
                    }
                    break;
                case WECHAT_PUBLIC_ACCOUNT:
                    AccessToken accessToken = wechatAPI.getOpenIdPublicAcct(code, config);
                    if (accessToken != null) {
                        log.info("WechatOpenIdCache[]findOpenId[] code:{},accessToken:{}", code,
                                accessToken);
                        openId = accessToken.getOpenid();
                    } else {
                        log.error("WechatOpenIdCache[]findOpenId[] get openId by code failed[] code:{}", code);
                        throw new WechatException("accessToken null error");
                    }
                    break;
                default:
                    throw new WechatException("env is illegal");
            }

            if (StringUtils.isEmpty(openId)) {
                log.error("WechatOpenIdCache[] findOpenId[]get openId null error");
                throw new WechatException("openId null error");
            }

            log.info("WechatOpenIdCache[]findOpenId[] set openId to Redis: code:{}, openId:{}", code, openId);
            operations.set(getKey(wxCode2openIdHead, code), openId);
            stringRedisTemplate.expire(getKey(wxCode2openIdHead, code), duration, TimeUnit.MINUTES);
        } else {
            log.info("WechatOpenIdCache[]findOpenId[] get openId from Redis, openId:{}", openId);
        }
        return openId;
    }

    private String getKey(String head, Object key) {
        return (head + key);
    }
}
